عندما ننجز عملية كتابة الى مقبض الملف بإستخدام اي من الدوال الكتابة print او syswrite في الواقع ان عملية الخرج لاتحدث فوراُ ، بمعنى اذا رغبنا في الكتابة الى الملف مع تلك الدوال سوف ينتظر النظام الى ان يقوم رأس الكتابة write head (بحيث يوجد لمحرك الاقراص disk drive "القرص الصلب" العديد من الاسطوانات تناسباً طردياً مع سعة القرص ولكل اسطوانة رأسان رأس يقراء ويكتب في السطح العلوي للسطوانة ورأس يقراء ويكتب في السطح السفلي ) بالوصول الى الموقع الصحيح لمحرك الاقراص وذلك بإخبار الاسطوانة platter بدوران لجلب الموقع الصحيح تحت ذلك الرأس ،وهذا الشئ ينجز في وقت بسيط جداً بالرغم من انة قد يكون ملحوظ على الحاسوب المحمول والحواسيب القديمة الذي يدور بشكل متقطع أسفل قرصه disk لتؤفير طاقة البطارية ،ولكن عمليات الخرج الاخرى قد تستغرق وقت أكثر بكثير وخصوصاً اذا كانت عمليات خاصة بالشبكة التي قد تستغرق اطول من ذلك الوقت حتى تكتمل ، ونفس الشيء مع الدخل .
أساسيات اللخبطة mismatch بين سرعة الحسابية وسرعة I/O :
عندما البرنامج ينفذ محتويات تكرار مالانهاية يمكن تنفيذ هذا التكرار مليون مره في الثانية ، الأ ان عملية دخل وخرج واحدة فقط قد تستغرق عدة ثواني للإكمال وللتغلب على هذة اللخبطة فأن نظام التشغيل الحديث يستعمل تقنية buffering و blocking .
تتألف تركيب الذاكرة المؤقتة(buffer) من وحدات فيزيائية (blocks) مرتبة في صفوف وأعمدة وكل خلية او غرفة مرقمة من صفر الى سعة هذة الذاكرة وكل block مكؤنة من 32 بايت ، وعملية التخزين buffering هي التخزين في تلك الذاكرة فعند اجراء عملية القراءة والكتابة من والى وحدات الادخال او الاخراج تستخدم عادة وحدة تخزين مؤقتة للتوفيق بين سرعة وحدة الادخال والاخراج وسرعة القناة او الذاكرة وتسمى بالـ Buffers .
لاتختلف فكرة التكتل Blocking حيث تكتل البيانات في ذاكرة مؤقتة وتجمع عدد من السجلات في كتلة فيزيائية واحدة على ان يترك الفراغ بين كتلة واخرى حيث يجتمع 4 سجلات في كتلة block واحدة ، أن الفائدة من التكتل لإقلال من زمن القراءة والكتابة والأسراع من زمن المعالجة حيث تقرأ (أو تكتب) من الوحدة الفيزيائية بإستخدام عملية قراءة (أو كتابة) واحدة إذ أن مجموع السجلات تقرأ مرة واحدة بإستخدام تعليمة قراءة واحدة بدلاً من قراءة كل سجل على حدة ، ومن المساوئ فأن التكتل تحتاج الى خورزميات وبرمجيات خاصة لإجراء عملية التكتل والفك للوصول الى السجلات المطلوبة بإظافة الى الحاجة الى مناطق تخزين مؤقتة .
إن الفكرة وراء buffering هي كما في الصورة اسفل ، فالـ Buffers تستدعي I/O المتضمن بواسطة البرنامج من عمليات الخرج والدخل الحقيقية التي تحدث على مستوى العتاد hardware ، فمثلاً عند إستدعاء الدالة print لان ترسل البيانات مباشراًُ الى terminal او كرت الشبكة او محرك الاقراص ، فبدلاًُ من ذلك تكتب ناتج البيانات الى مساحة الذاكرة ( وهذا الحدث سريع بسبب ان الكتابة الى الذاكرة سريع ) وفي هذة الاثناء في الشكل الغير متوافقية زمنياً asynchronous فأن نظام التشغيل يقراء البيانات المكتوبة سابقاً من الـ buffer وينجز الاعمال الضرورية للكتابة المعلومات الى أجهزة العتاد.
في الصورة فأن الـ Buffers تساعد على حل اللخبطة بين سرعة الحساب وسرعة I/O .
بنفس الطريقة لعمليات الدخل فأن نظام التشغيل يستلم البيانات من أجهزه الدخل النشطة ( keyboard, disk drive, network card) ويكتب تلك البيانات الى input buffer في مكان ما في الذاكرة ، وتبقى البيانات في input buffer الا ان يقوم السكربت من استدعى <> (او الدالة read) وعند استدعاءها فأن نظام التشغيل يقوم بنسخ البيانات من buffer الى فضاء الذاكرة المقابل للمتغير في البرنامج.
فائدة buffering هام خصوصاً إذا برنامجك ينجز I/O بشكل متقطع "bursty" لان ذلك يؤدي الى قرءات وكتابات عديدة من الحجم والوقت المتقلب ،فبدلاً من الانتظار لكل عملية الى أن تكتمل على مستوى العتاد ، فأن البيانات تخزن بشكل مؤقت وأمان في نظام التشغيل وتجرف الية "flushed"—وتمر الى جهاز الخرج —حينما يكون العتاد يقبل التدفق الى أسفل downstream الجهاز.
في الصورة أعلى فأن buffers تنجز في مبدأ FIFO (الداخل اولاً خارج اولاً ) فعند كتابة بيانات فأن نظام التشغيل يبداء بكتابة بيانات جديدة في بداية الـbuffer ويشير اليها بأثنين من المؤشرات لكل I/O buffers فمؤشر الكتابة يوضع أينما تدخل البيانات الجديدة ومؤشر القراءة موقعة في المكان التالي للبيانات المتحركة في الـ buffer ، فمثلاً عند عملية الكتابة بواسطة الدالة print فسوف تضاف البيانات المتضمنة في هذة الدالة الى output buffer مع تحريك مؤشر الكتابة عند كل كتابة ،وعند الانتهاء فأن نظام التشغيل يقرا البيانات من بداية مؤشر القراءة وتنسخ الى جهاز العتاد .
حجم I/O buffer ناقص المسافة بين مؤشر الكتابة ومؤشر القراءة هي الكمية المتبقية من المساحة المحررة ، اي أن المساحة الحرة = حجم I/O buffer – ( المسافة بين مؤشر الكتابة ومؤشر القراءة )
، فإذا كان برنامجك يكتب البيانات أسرع من جهاز الخرج التي يستلمها ، فأن الـ buffer يعبئ الى نهاية مساحتة الحرة بالقيمة صفر وماالذي نتوقع ان يحدث بعد ذلك ؟
فعدم وجود غرف للبيانات الجديدة في الـ buffer في هذة الاثناء فأن عملية الخرج لايمكن أن تنجح مباشراً نتيجتاً لتكتيل عملية الكتابة لذلك البرنامج يتؤقف للفتره زمنية غير محدودة على الدالة print او syswrite المكتلة (أو الموقوفة) ، وعندما تتراكم في output buffer سوف تنظف بشكل مستمر وهكذا الغرفة سوف تستلم البيانات الجديدة مرة اخرى ، وستكون عملية الخرج في هذا الوقت غير متكتلة unblocking والدالة print او syswrite سوف تعاد في هذة الاثناء .
وبشكل مماثل فأن القراءة ستكون متكتلة block عندما الـ input buffer يكون فارغاً أو خالي من البيانات ، وتكتل حينما يكون كمية المساحة الحرة تساوي حجم الـ buffer في هذة الحالة بإستدعاء read او sysread فسوف تكتل حتى تدخل بعض البيانات الجديدة الي buffer وهناك الدوال تقراء البيانات.
فالـBlocking في اغلب الوقات السلوك المرغوب لكن في بعض الاحيان تحتاج الى سيطرة اكثر للـ I/O ، فهناك العديد من التقنيات لإدارة blocking ، كاتقنية Timing Out Slow System Calls التي ستناقش في فصل الأشارات لاحقاًُ والتي تستعمل الإشارات لإجهاض عمليات I/O قبل ان يحن الأوان إن استغرقت وقتاً طويلاً ، هناك تقنية اخرى باستعمال اربعة وسطاء للدالة select لاستدعاء النظام لختبار مقبض الملف لقراءة سطورة لنجز I/O قبل الصنع الفعلي للإستدعاء القراءة والكتابة ، وهناك تقنية اخرى وهي لمقبض الملف الـnonblocking والتي تسبب لعملية القراءة او الكتابة الى الإعادة مباشرتاً مع كود الخطأ ان كانت العملية block ستناقش في هذا الجزء.
بالرغم من أننا تحدثنا عن single buffer لعمليات الدخل والخرج I/O على مقبض الملف الا أن هناك العديد من buffers بإختلاف طبقات layers أنظمة التشغيل ، فعلى سبيل المثال عندما نكتب الى ملف القرص فهناك buffer وطئ المستوى على قرص العتاد نفسه ، وأخر على المحرك driver (سواء كان هذا المحرك SCSI او IDE التي تقوم بإسيطرة على القرص disk بحيث لا يمكن التعامل مع وسائط التخزين Storage Media إلا في وجود المحركات او المشغلات المناسبة وتعتبر هذه المشغلات وحدات إدخال ووحدات إخراج معا I/O Devices)، وواحد اخر في محرك نظام الملفات filesystem ، وأخر في مكتبة السي القياسية المستعمل مع البيرل .
فلا يمكنك السيطرة أو حتي الوصول لإغلب هذة buffers مباشرتاً ولكن هناك طبقة واحدة من buffer التي يجب ان تكون مدرك لها ،فاعديد من عملية PerlIO تتدفق من خلال "stdio" او Standard-IO وهي مكتبة لغة السي القياسية للدخل والخرج والتي تملك I/O buffers خاصة بها ومستقلة عن نظام التشغيل .
توقع ان مكتبة stdio طبقة معدة على رأس نظام التشغيل ، والتي تجعل نظام التشغيل ينظر الية كما لو كان برنامج سي وبشكل مشابة مع مكتبة I/O القياسية لباسكال فهي تجعل نظام التشغيل ينظر اليه كما لو كتب في الباسكال . |
فعند استعمال معامل البيرل <> أو read ، print فأن كل هذة العمليات تستخدم stdio فمثلاًُ عند إستدعى الدالة print فأن البيانات تنتقل الى الـ output buffer لطبقة stdio قبل أن ترسل إلى نظام التشغيل نفسة ، ونفس الشئ مع <> , read فكليهما تقراء البيانات من buffer الـstdio بدلاً من نظام التشغيل ، ولكل مقبض ملف له مجموعة خاصة من buffers للدخل والخرج (input buffer, output buffer) وذلك لإسباب الكفاءة والسرعة ، فالـstdio تنتظر لذاكرتها المؤقتة للخرج output buffers حتي تصل الى حجم معين قبل جرف flushing محتوها الى نظام التشغيل .
فبشكل عادي فأن التخزين المؤقت للـ stdio لايوجد فيها مشاكل في الوقت الحاضر الا قد تواجهك بعض المشاكل عند عمل مع أنواع sophisticated للخرج والدخل كاعمليات الشبكة مثلاً بإعتبر ان حالة التطبيق هي للمشاركة وكتابة بياناتة الى السيرفر البعيد وبإنتظار الرد ثم إرسل بيانات اكثر اضافية الية ، فقد تعتقد ان البيانات قد إرسلت عبر الشبكة لكنها في الحقيقة لم ترسل بعد حيث مازلت بيانات الخرج تعد في buffer الـ stdio المحلي وفي حالة إنتظار للبيانات الاضافية القادمة قبل جرف flushing الـbuffer ، فأن السيرفر البعيد لان يستلم البيانات وهكذا لان يعيد ابداً الرد ، وبرنامجك لن يستلم الرد وهكذا لايرسل بيانات اضافية ابداً ويبقى في حالة جمود (Deadlock) او حالة إنتظار دائمة .
على النقيض من ذلك مع التخزين المؤقت buffering للمستوى الأوطئ المنجزة بواسطة نظام التشغيل نفسة التي ليست بنفس المعني السابق ، فانظام التشغيل سوف يحاول تسليم البيانات مهما كانت في output buffers بتاعة طالما العتاد يقبلها .
هناك طريقتين للتخزين المؤقت stdio buffering :
الاولة بواسطة فتح النمط "autoflush" للمقبض الملف ، ويطبق هذا النمط للعمليات الخرج فقط ، وعندما ينشط فأن المفسر يخبر stdio إلى جرفflush بافر مقبض الملف filehandle's buffer في كل مرة تستدعي الدالة print .
ولفتح النمط autoflush يوضع المتغير الخاص $| بقيمة صحيحة true ، و التأثير على مقبض الملف الحالي أو المحدد بواسطة الدالة select بوضع الدالة اولاً ثم وضع $| ، فمثلاً لفتح النمط على مقبض الملف FH :
my $previous = select(FH); $| = 1; select($previous);
ويمكن إختصار التعبيرالسابق :
select((select(FH),$|=1)[0]);
على اي حال فأن النمط يقوم بالتنظيف اكثر مع الموديل IO::Handle او IO::File بواسطة وضع الطريقة autoflush الى مقبض الملف
use IO::Handle; FH->autoflush(1);
على سبيل المثال عند كتابة برنامج لطباعة الاحرف مع print
#!/usr/bin/perl
use warnings;
use strict;
for ("a".."z") {
print "$_";
sleep 1;
}
print "\n";
فأن أغلب أنظمة التشغيل يجب ان تتنظر ستة وعشرون ثانية اولاً قبل طباعة الاحرف ولان تكتب(أو تقراء ) شيئاً الى مقبض الملف حتي ينهي السطر ، حيث في هذة الاثناء تحفظ في ذاكرة مؤقتة وعند الانتهاء من الحفظ سوف يتصل الى مقبض الملف
كما سبق نستطيع اخبار البيرل لايقاف هذا العمل بواسطة تعديل المتغير الخاص $| بوضع القيمة 1 فالبيرل سوف تعيد off buffering للمقبض المحدد الحالي وهو stdout، اما عند وضع بالقيمة صفر فهي تخبر بإستعمال output buffering
#!/usr/bin/perl
use warnings;
use strict;
$ |=1 ;
for ("a".."z") {
print "$_";
sleep 1;
}
print "\n";
نمط autoflush لايقوم بتعطل التخزين المؤقت buffering فهو مجرد يقوم بمنح مقابض الملف المخزنة لكي تعيد كل سطر مخزن في الذاكرة المؤقتة . |
الطريقة الاخرى عن طريق Unbuffered I/O لتفأدي مشاكل stdio buffering بواسطة إستدعاء الدوال sysread و syswrite لتتجاوز مكتبة stdio والذهاب الى ملف الوصف مباشرتاً بإستعمال عمليات I/O لإستدعاءات النظام ، وفائدتها مهمة حيث تشغلهم داخلياً مع استدعاءات النظام المنخفضة المستوى للدخل والخرج low-level I/O ، كما الدالة select مع الاربعة الوسطاء وايضاً تقنية nonblocking I/O .
دوال sys*() لتتجاهل طبقة standard IO وهو الاختلاف في السلوك الدالة read والدالة sysread عند جلب اليها قطعة كبيرة من البيانات المتؤفرة ، في حالة الدالة read فستكون الدالة في بلوك غير محدود block indefinitely حتي يتم جلب الكمية المطلوبة من البيانات بالتمام او الى ان يصادف نهاية الملف قبل الكمية المطلوبة وتعيد كل شيء الى نهاية الملف ، على النقيض من ذلك الدالة sysread التي يمكن ان تعيد جزء من القراءة وأن لم تستطع قراءة كل البيانات المطلوبة فسوف تعيد البيانات المتؤفرة ، فالدالة sysread سوف تكتل حتي انها تستطيع من اعادة على الاقل 1 بايت ، وهذا الشيء مهم جداً في اتصالات الشبكات حيث البيانات تصل الى حجم متقلب ولذا فأن sysread و syswrite تفضل في العديد من برامج الشبكة .
#!/usr/bin/perl
# sysread.pl
use warnings;
use strict;
use POSIX;
my $result;
die "Usage: $0 file \n" unless @ARGV;
sysopen HANDLE, $ARGV[0], O_RDONLY|O_NONBLOCK;
# read 20 chrs into $result
my $chrs = sysread HANDLE, $result, 20;
if ($chrs == 20) {
# got all 20, try to read another 30 chrs into $result after the first 20
$chrs += sysread HANDLE, $result, 30, 20;
print "Got '$result' \n";
if ($chrs < 50) {
print "Data source exhausted after $chrs characters \n";
} else {
print "Read $chrs characters \n";
}
} elsif ($chrs > 0) {
print "Got '$result' \n";
print "Data source exhausted after $chrs characters \n";
} else {
print "No data! \n";
}تعيد الدالة sysread عدد الإحروف التي قراءت بنجاح ،قد تقراء اقل من العدد المطلوب او قد لاتقراء شيئاً في حالة عدم وجود بيانات او 0 من البيانات ، ولاحظ اذا لم يوضع O_NONBLOCK فأن الدالة سوف تنتظر وصول بيانات اكثر بدلاً من أعادة 0
السبب الرئيسي لإستعمال sysopen على open هو nonblocking IO فعادتاً عند اجراء عملية قراءة أو كتابة (بواسطة دوال الـsysread or syswrite ) فأن النظام سوف ينظر للعملية الى أن تكتمل ، ففي حالة القراءة فان البيرل ستنتظر الدخل الى ان يكتمل الوصول ثم بعد ذلك إعادة السيطرة للبرنمجنا ، فقد لانرغب بإنتظار لعمل اشياء اخرى في تلك الاثناء ولذالك سوف نستخدم العلام O_NONBLOCK مع الدالة sysopen (ولسوء حظ مبرمجين الونيدوز ليس لهم فرصة في العمل هنا بسبب عدم تدعيم هذا العلام في الوقت الحالي)
use Fcntl;
# open serial port read only, nonblocking
sysopen SERIAL, '/dev/ttyS0', O_RDONLY|O_NONBLOCK;
# attempt to read characters
my $key;
while (sysread SERIAL, $key, 1) {
if (defined $key) {
print "Got '$key' \n";
} else {
warn "No input available \n";
# wait before trying again
sleep(1);
}
}
# close the port
close SERIAL;
عندما النمط nonblocking ينشط ، فسيحاول القراءة من مقبض الملف ، وعندما تكون البيانات غير متؤفرة فسوف يظهر الخطأ EAGAIN في المتغير الخاص $! ، يمكن ان نحصل على الترميز symbol للـEAGAIN من وحـدة POSIX ، لذلك فأن أفضل طريقة لكتابة البرنامج السابق بأن يكون :
use POSIX qw(EAGAIN);
use Fcntl;
# open serial port read only, nonblocking
sysopen SERIAL, '/dev/ttyS0', O_RDONLY|O_NONBLOCK;
# attempt to read characters
my $key;
while (sysread SERIAL, $key, 1) {
if (defined ($key)) {
print "Got '$key' \n"
} else {
if ($!==EAGAIN) {
warn "No input available \n";
# wait before trying again
sleep(1);
} else {
warn "Error attempting to read: $! \n";
last;
}
}
}
# close the port
close SERIAL;
تؤفر البيرل العديد من الوحدات كعائلات IO:: لتفاعل السهل مع مقابض الملفات بواسطة الكائنات الموجهه ، IO::Handle تقوم بتبسيط مقبض الملف لإجراء العمليات المختلفة بينما IO::File فهي طبقة فرعية من IO::Handle ، والترتيب الهرمي لطبقة IO::Handle بالشكل التالي

تؤفر وحـدة IO::Handle مقبض ملف ابتدائي مشتركة للمقابض الثلاثة الافتراضية أو إنشاء مقبض ملف مخفي بواسطة الطريقة new التي تعيد عند استدعها مرجع المقبض ، و تعيد وحدة IO::File أيضاً مرجع لمقبض الملف بنفس الشكل لكن ملف حقيقي متضمن ، اما وحـدة IO::Dir للتعامل مع المجلدات ،وهناك أنواع خاصة لمقبض كالـ IO::Socket و IO::Pipe.
#!/usr/bin/perl
use IO::Handle;
STDOUT->print("Built-in function"); #does not need IO::Handle
STDOUT->autoflush(1); #added by IO::Handle module
my $fh=new IO::Handle;
open($fh, "myfile.txt");
المقابض الثلاثة تعين بشكل آلي عند إستخدام الطرق للإستعمالات على اكثر من مقبض ، فالطريقة autoflush تؤدي التفاعل الاكثر سهوله وتكافئ المتغيرالخاص $|
لدى وحدة IO::Handle العديد من الطرق المختلفة وتصنف هذة الطرق الى : طرق الانشاء وطرق داخلية built-in وطرق الإعدادات للتقارير وطرق اخرى مفيدة
| الطريقة | الحدث |
|---|---|
| new | انشاء كائن جديد من IO::Handle على سبيل المثال ،
لإنشاء مقبض ملف ويربط معة الملف المفتوح |
| new_from_fd | انشاء كائن جديد من IO::Handle وينسخ فيه المقبض $fh أوملف الوصف المعطى ، على سبيل المثال ملف الوصف هو رقم الملف الذي يمثل الأتصال الخام الى الملف او الجهاز ويحدد بالرقم او بالاسم 0 ، 1 ،2 للـSTDINو STDOUT و STDERR على التوالي او ملف موجود من خلال الدالة fileno ولاحظ ان هذة الدالة تحقق النمط &= للدالة open |
| الطريقة | الحدث |
|---|---|
| close | إغلاق الملف |
| eof | إختبار شرط نهاية الملف |
| fileno | إعادة ملف الوصف (رقم الملف) من مقبض الملف |
| format_write | كتابة الـ format string (مكافئة للدالة write ) |
| getc | إدخال حرف فقط |
| read | قراءة عدد محدد من البايت |
| الطباعة الى الملف | |
| printf | الطباعة مع اجراء عملية الـ Format a string الى الملف |
| stat | إعادة بعض المعلومات عن الملف |
| sysread | أنجاز القراءة بواسطة النظام |
| syswrite | أنجاز الكتابة بواسطة النظام |
| truncate | إزالة محتوى الملف ماعدا طول البايت المحدد في البداية |
طرق الإعدادات لمقبض الملف وكلاً منهم مرتبطة بمتغير خاص الذي يكافئ وظيفة الطريقة في الناتج المحدد للمقبض الملف ، فتلك الطرق والمتغيرات الخاصة المتعلقة معها لديها ايضاً مجموعتين : اولئك الذي يعملون على كل مقبض ملف basis والاخر يعملون كالـglobal في التأثير ويطبق على كل مقابض الملفات .
وهنا الجدول لكل مقبض ملف basis
| الطريقة | المتغير | الحدث |
|---|---|---|
| autoflush | $| | عمل flush آلياً، على سبيل المثال
|
| format_page_number | $% | رقم الصفحة الحالية لقناة الخرج المحددة حالياً |
| format_lines_per_page | $= |
طول الصفحة الحالية (printable lines) لقناة الخرج المحددة حالياً
وضع طول للصفحة بطول 66 سطر |
| format_lines_left | $- | عدد الأسطر اليسار على الصفحة لقناة الخرج المحددة حالياً |
| format_name | $~ | الأسم الحالي لتقرير الـformat لقناة الخرج المحددة حالياً |
| format_top_name | $^ | اسم رأس صفحة الـformat لقناة الخرج المحددة حالياً |
| input_line_number | $. |
رقم السطر الحالي
لاحظ أنة يمكن ان يوضع بهذة القيمة وبالرغم انة يعتبر عادة للقراءة فقط |
والمتغيرات الخاصة وطرق IO::Handle الـglobal في الجدول لكن يمكن ان توضع عن طريق الطريقة الملائمة
| الطريقة | المتغير | الحدث |
|---|---|---|
| format_line_break_characters | $: | The current set of characters after which a string may be broken to fill continuation fields (starting with ^) in a format. |
| format_formfeed | $^L | Which formats output as a form feed. |
| format_field_separator | $, | The string output between items in a print
statement. By default, nothing. To print out
comma-separated values, set to ,:
|
| output_record_separator | $\ | The string output after the end of a print
statement. By default, nothing. To print out lines
automatically terminated by newlines, set to
"\n":
|
| input_record_separator | $/ | The string used to separate lines for the readline
operator. By default, it is \n. To read in para-
graph mode, set to an empty string. To read a
whole file at one go (slurp mode), set to undef:
|
الطرق المفيدة في الجدول التالي
| الطريقة | الحدث |
|---|---|
| fdopen FILENO | ربط مقبض الملف مع الاسم المعطي للمقبض الملف الى كائن IO::Handle على سبيل المثال
|
| opened |
تعيد true أذا كائن مقبض الملف هو مفتوح حالياًُ ، وغير ذلك فهو false ، فمثلاًُ
|
| getline |
تقراء وتعيد السطر التالي (سطر واحد) من الملف ، على سبيل المثال :
|
| getlines |
تقراء وتعيد كل السطور المتؤفرة للملف ، على سبيل المثال
|
| ungetc CHAR |
دفع حرف للخلف الى الـinput buffer ، على سبيل المثال
الحرف يجب ان يحدد بالـASCII ويدفع حرف واحد فقط للخلف |
| write BUF, LEN, OFFSET |
المكائفة للدالة syswrite حيث تكتب برقم المعطى من الاحرف الى مقبض الملف على سبيل المثال :
فالطريقة write مناقضة للطريقة read فهي تكتب البايتات المتدفقة stream الى مقبض الملف وتعيد عدد الكتابات التي نحجت وتشابة syswrite ماعدا انها تسخدم الـstdio buffering ، فبشكل متاقض فهي مضافة للتقارير وتقابل الدالة format_write . |
| error | تعيد true إذا مقبض الملف واجة أي خطاء عند الفتح او من الإستدعاء الاخير للطريقة clearerr . |
| clearerr | تنظيف شرط الخطأ للمقبض الملف (كالشرط المضمن في نهاية الملف EOF ) فعلي سبيل المثال
|
| sync |
حالة التزامن Synchronize في الذاكرة لجميع الملفات المفتوحة مع حالتهم على القرص وتحدث وتغير جميع نظام الملفات file system الاخرى ، فعلى سبيل المثال
لاحظ بأن ذلك في ؤظيفة مستوى النواة التي لاتتؤفر على كل الأرصفة ، فهي لاتعمل على كل نظام الملفات المستندة عليها ولاتعمل flush لخرج التخزين المؤفت على مستوى مقبض الملف —تستعمل flush للذلك . |
| flush |
عمل Flush لخرج المخزن مؤقتاً buffered output في مستوى التطبيق فمثلاً :
فهذة الطريقة ستعمل flush لإي بيانات التي تخزن buffered في اما بواسطة block أو بواسطة buffering أسفل الى نظام التشغيل ، فهي غير مضمونة لتلك البيانات المكتوبة فعليلاً على اي حال sync تعمل ذلك |
| printflush ARGS |
تمكين نمط autoflush لوسيط print للمقبض الملف وثم بعد ذلك إعادة تخزين حالة autoflush ، فعلى سبيل المثال :
|
| blocking 0|1 |
وضع النمط اما blocking أو nonblocking على مقبض الملف المحدد وتعيد القيمة التي وضعت سابقاًَ ، فعلى سبيل المثال :
|
من خلال الطريقة new_from_fd والطريقة fdopen يمكن حفظ وإعادة تخزين الكائنات في اكثر من طريقة فمثلاً لمكائفة النمط >&FILEHANDLE
use IO::Handle;
$SAVEOUT = IO::Handle->new_from_fd(STDOUT,">");# حفظ STDOUTالى المقبض$SAVEOUT
open(STDOUT, ">myfile.txt"); # اعادة فتح
STDOUT->print("Yippy yie yay!\n");
STDOUT->fdopen($SAVEOUT,">"); # اعادة فتح STDOUT على القيمة المحفوظة
STDOUT->print("BBBB!\n");
وحدة IO::File تتفاعل اكثر مع الملفات وغير محددة لطريقة الفتح مع الدالة open ، على سبيل المثال لفتح ملف للكتابة
use IO::File;
$fh = new IO::File; # create a filehandle object
$fh->open("> myfile") or die "Unable to open: $!";# open a file
ويمكن انشاء مقبض وفتح الملف في وقت واحد
$fh = new IO::File("> myfile") or die "Unable to open: $!";
حيث ان لدى الطريقة new ثلاثة وسطاء وهم :
$fh = IO::File->new($filename [,$mode [,$perms]])
وتمثل بوسيطين كما الدالة open لنمط النصي والوسيط الثالث لعبور التصريح ، ويمكن إستعمال الـدالة sysopen بشكل الآلي أن اعطيت بانمط عددي بدلاً من نصي :
# 'IO::File' open for read/write using 'open' $fh = new IO::File ($filename, '+<'); # 'IO::File' open for read/write using 'sysopen' $fh = new IO::File ($filename, O_RDWR);
فالنمط العددي للموديل IO::File تكشف آلياً لعبوره الى الدالة sysopen بدلاُ من الدالة open
بإستدعى الطريقة new فسوف تعيد كائن المقبض الذي يمكن ان يستعمل لمختلف العمليات بأستدعاء اي طريقة من الطبقة الفرعية IO::File او من الوحـدات المؤرثة منها IO::Handle و IO::Seekable
$fh->autoflush(1); # IO::Handle
$fh->seek(0, SEEK_END); # IO::Seekable
$fh->print("Message...\n"); # built-in
$fh->close(); # IO::File
$fh->open("> $anotherfile"); # IO::File
يمكن ان نستخدم الطريقة read
$bytes = $fh->read($buffer,$length ",$offset")
وللكتابة بنفس الطريقة اما
$fh->print("Function calls are for the birds.\n");
or
print $fh "Object methods are too effete.\n";
فعلى سبيل المثال لقراءة السطر الاول من الملف المحلي
lgetl.pl—Read the first line of a local file
#!/usr/bin/perl use IO::File; my $file=shift; my $fh=IO::File->new($file); my $line=<$fh>; print $line;
في المثال شحن الموديل IO::File باستعمل التوجيه use ثم أخذ اول وسيط من نافذة الاوامر بإستعمال الدالة shift ويخصيص الى المتغير $file ثم في السطر الرابع فتح الملف بأستدعى IO::File->new الطريقة new لإنشاء مقبض مرتبط بالعتاد على الجهاز المحلي وثم اجراء عمليات الخرج اوالدخل للمقبض
% perl lgetl.pl giants_star.txt "Reintegration complete," ZORAC advised. "We're back in the universe."
بنفس عملية القراءة للسطر الاول من السيرفر البعيد
lgetr.pl—Read the first line from a remote server
#!/usr/bin/perl use IO::Socket; my $server=shift; my $fh=IO::Socket::INET->new($server); my $line=<$fh>; print $line;
لاحظ ان المقبس مشابة IO::File حيث يتم شحن الموديل IO::Socket باستعمل التوجيه use ثم أخذ اول وسيط من نافذة الاوامر بإستعمال الدالة shift ويخصيص الى المتغير $server ثم في السطر الرابع (الطبقة IO::Socket::INET مستندة على انصالات Internet ) فتح المقبس بإستدعى IO::Socket::INET->new() الطريقة new لإنشاء مقبس مرتبط بخدمة معينة مشغلة على الجهاز البعيد في الشبكة وثم اجراء عمليات الخرج اوالدخل للمقبض وسوف نتطرق فيما بعد الى المقابس.
% perl lgetr.pl wuarchive.wustl.edu:daytime Tue Aug 8 06:49:20 2004 % perl lgetr.pl wuarchive.wustl.edu:ftp 2:220 wuarchive.wustl.edu FTP server (Version wu-2.6.1(1) Thu Jul 13 21:24:09 CDT 2004) ready. % perl lgetr.pl mail.hotmail.com:smtp 2:220-HotMail (NO UCE) ESMTP server ready at Tue Aug 08 05:24:40 2004